using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Instedd.Labs.Geo.Library.Rss;
using Instedd.Labs.Geo.Library.Kml;

namespace Instedd.Labs.Geo.Library.Rss
{
    public class RssWriter
    {
        RssWriterSettings writerSettings;

        public void WriteRss(XmlWriter writer, RssFormat rss)
        {
            WriteRss(writer, rss, new RssWriterSettings());
        }

        public void WriteRss(XmlWriter writer, RssFormat rss, RssWriterSettings rssWriterSettings)
        {
            writerSettings = rssWriterSettings;

            writer.WriteStartElement("rss");
            writer.WriteAttributeString("version", "2.0");
            writer.WriteAttributeString("xmlns", "dc", null, "http://purl.org/dc/elements/1.1/");

            if (rssWriterSettings.UseGeoRss)
            {
                writer.WriteAttributeString("xmlns", "georss", null, "http://www.georss.org/georss");
            }
            if (rssWriterSettings.UseGeo)
            {
                writer.WriteAttributeString("xmlns", "geo", null, "http://www.w3.org/2003/01/geo/wgs84_pos#");
            }

            rss.Channels.ForEach(delegate(Channel c) { WriteChannel(writer, c); });

            writer.WriteEndElement();
        }

        private void WriteChannel(XmlWriter writer, Channel channel)
        {
            writer.WriteStartElement("channel");
            writer.WriteStartElement("title");
            writer.WriteValue(channel.Title);
            writer.WriteEndElement();
            writer.WriteStartElement("link");
            writer.WriteValue(channel.Link);
            writer.WriteEndElement();
            writer.WriteStartElement("description");
            writer.WriteValue(channel.Description);
            writer.WriteEndElement();
            channel.Items.ForEach(delegate(Item item) { WriteItem(writer, item); });
            writer.WriteEndElement();
        }

        private void WriteItem(XmlWriter writer, Item item)
        {
            writer.WriteStartElement("item");
            writer.WriteStartElement("guid");
            writer.WriteAttributeString("isPermaLink", "false");
            writer.WriteValue(item.Id.ToString());
            writer.WriteEndElement();
            writer.WriteElementString("title", item.Title);
            writer.WriteElementString("description", item.Description);
            writer.WriteElementString("link", item.Link);
            writer.WriteElementString("pubDate", item.PubDate.ToString("r"));
            writer.WriteElementString("dc", "creator", null, item.Creator);
            if (item.LatLong != null)
            {
                WriteLatLong(writer, item.LatLong);
            }
            if (item.Line != null)
            {
                WriteLine(writer, item.Line);
            }


            writer.WriteEndElement();
        }

        private void WriteLatLong(XmlWriter writer, LatLong location)
        {
            if (writerSettings.UseGeoRss)
            {
                writer.WriteElementString("georss", "point", null, location.ToString());
            }
            if (writerSettings.UseGeo)
            {
                // Adding both GeoRss & Geo  confuses GM who renders each item twice... :S
                writer.WriteElementString("geo", "lat", null, location.Lat.ToString());
                writer.WriteElementString("geo", "long", null, location.Long.ToString());
            }
        }

        private void WriteLine(XmlWriter writer, Line path)
        {
            string[] coordinates = path.Coordinates.ConvertAll<string>(delegate(LatLong location) { return location.ToString(); }).ToArray();
            string coordinatesValue = string.Join(" ", coordinates);
                
            if (writerSettings.UseGeoRss)
            {
                writer.WriteElementString("georss", "line", null, coordinatesValue);
            }
            if (writerSettings.UseGeo)
            {
                // TODO: To be implemented
                throw new NotImplementedException("The RssWriter doesn't implement the Geo format for lines.");
            }

        }
    }

}
